fa.define(['layer', 'fa_util','fa_log'], function (exports) {
    'use strict';
    let MOD_NAME = "fa_intro";
    let layer = layui.layer;
    let util = layui.fa_util,
    log = layui.fa_log.getLog(MOD_NAME);
    let FaIntro = function () {
        this.steps = [];
        this.idx = 0;
        this.box;//高亮显示
        this.boxp;//阻止点击事件
        this.boxtool;//工具
        this.options = {
            name: 'fa_intro',
            showTime: 3,
            eleOncls: 'fa-intro-on',
        }
        this.init();
    }

    FaIntro.prototype.noPlay = function () {
        let dict = layui.data(MOD_NAME);
        let c = dict[this.options.name] || 0;
        log.log(c, this.options.showTime);
        if (c > this.options.showTime) { return true; }
        layui.data(MOD_NAME, { key: this.options.name, value: 1 + c })
        return false;
    }

    /**
     * 开始
     */
    FaIntro.prototype.start = function () {
        if (this.noPlay()) { return; }
        this.shade();//打开shade
        this.initBox();//初始化tipbox
        this.on(this.idx);//展示被引导元素
    }


    /**
     * 关闭
     */
    FaIntro.prototype.close = function () {
        this.off();//移除元素样式
        this.unShade();//移除shade
        this.box.remove();//移除tipbox
        this.boxp.remove();
        this.boxtool.remove();
        // layui.data(MOD_NAME, { key: this.options.name, value: this.options.showTime + 1 })
    }
    /**
     * 上一个
     */
    FaIntro.prototype.pre = function () {
        this.off(this.idx);
        this.on(--this.idx);
    }
    /**
     * 下一个
     */
    FaIntro.prototype.next = function () {
        this.off(this.idx);
        this.on(++this.idx);
    }

    FaIntro.prototype.initBox = function () {
        this.box = document.createElement('div');
        this.box.className = "fa-intro-box";
        document.body.appendChild(this.box);
        this.boxp = document.createElement('div');
        this.boxp.className = "fa-intro-boxp";
        document.body.appendChild(this.boxp);
        this.boxtool = document.createElement('div');
        this.boxtool.className = "fa-intro-boxtool";
        this.boxtool.innerHTML = [
            "<div id='intro_tip' class='tip'>提示</div>",
            "<div class='btn'>",
            "<a id='intro_pre' class='layui-btn layui-btn-xs'>上一步</a>",
            "<a id='intro_next' class='layui-btn layui-btn-xs'>下一步</a>",
            "</div>"
        ].join("");
        document.body.appendChild(this.boxtool);
        this.intro_tip = document.getElementById('intro_tip');
        this.intro_pre = document.getElementById('intro_pre');
        this.intro_next = document.getElementById('intro_next');
        this.intro_pre.addEventListener('click', () => { this.pre() })
        this.intro_next.addEventListener('click', () => { this.next() })
    }
    FaIntro.prototype.resize = function (ele, rect) {
        rect.w && (ele.style.width = rect.w + "px");
        rect.h && (ele.style.height = rect.h + "px");
        rect.l && (ele.style.left = rect.l + "px");
        rect.t && (ele.style.top = rect.t + "px");
        rect.r && (ele.style.right = rect.r + "px");
        rect.b && (ele.style.bottom = rect.b + "px");
    }

    FaIntro.prototype.off = function (idx) {
        if (!idx) {
            this.steps.forEach(x => util.removeClass(x.ele, this.options.eleOncls));
            return;
        }
        if (idx >= 0 && idx < this.steps.length) {
            util.removeClass(this.steps[idx].ele, this.options.eleOncls);
            return;
        }
    }

    FaIntro.prototype.on = function (idx) {
        if (idx < 0 || idx >= this.steps.length) {
            this.close();
            return;
        }
        let step = this.steps[idx];
        let ele = step.ele;
        let intro = step.intro || "";
        if (!ele) return;
        let rect = ele.getBoundingClientRect(), opts = { w: rect.width, h: rect.height, t: rect.y + window.scrollY, l: rect.x + window.scrollX };
        //移动tipbox的位置
        this.resize(this.box, opts);
        this.resize(this.boxp, opts);
        //工具类位置需要再计算
        let bodyRect = document.body.getBoundingClientRect();
        let toolRect = this.boxtool.getBoundingClientRect();
        let x = opts.w + opts.l + 10, y = opts.h + opts.t + 10;

        if (bodyRect.width - x < opts.l) { x = opts.l - toolRect.width - 10 }
        if (bodyRect.height - y < opts.t) { y = opts.t - toolRect.height - 10 }

        //x、y轴无可用空间
        if (x < 0 || toolRect.width + x > bodyRect.width) { x = 10; }
        if (y < 0 || toolRect.height + y > bodyRect.height) { y = 10 }
        this.intro_tip.innerHTML = intro;
        this.resize(this.boxtool, { l: x, t: y });
        //高亮被选中的ele
        //问题：启用动画时、box还没过去、就已经高亮了
        util.addClass(ele, this.options.eleOncls);
    }

    /**
     * 将被介绍ele制作成图片放到tipbox内
     * <br/>
     * 问题：遮罩层会被一同绘制成图片
     * 需要引入加载 html2canvas.js 
     * @param {*} ele 
     */
    FaIntro.prototype.fillSelf = function (ele) {
        this.tipbox.innerHTML = "";
        html2canvas(ele).then(canvas => {
            this.tipbox.appendChild(canvas);
        });
    }


    /**
     * 通过htl属性自动加载引导步骤
     * 1、class 包含 fa-intro
     * 2、data-step="1",引导顺序
     * 3、data-intro ,介绍内容
     * 4、data-position,提示位置
     * 
     */
    FaIntro.prototype.init = function () {
        this.steps = [];
        document.querySelectorAll('.fa-intro').forEach(x => {
            this.steps.push({ ele: x, intro: x.dataset['introDesc'], order: parseInt(x.dataset['introOrder']) });
        });
        this.steps.sort((a, b) => { return a.order - b.order });
        log.log(this.steps);
    }
    /**
     * 遮罩
     */
    FaIntro.prototype.shade = function () {
        this.shadebox = document.createElement('div');
        this.shadebox.className = 'fa-intro-shade';
        this.shadebox.addEventListener('click', () => {
            this.close();
        })
        document.body.appendChild(this.shadebox);

    }

    /**
     * 取消遮罩
     */
    FaIntro.prototype.unShade = function () {
        this.shadebox.remove();
    }

    FaIntro.prototype.setOptions = function (options) {
        this.steps = options.steps || this.steps;
        delete options.steps;
        util.extend(this.options,options);
    }

    exports(MOD_NAME, new FaIntro());
});